using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Printing;
using System.Collections;
using System.Data;
using System.Collections.Generic;

namespace Gencode.PrsUtil.Print
{
	/// <summary>
	/// Summary description for PrinterClass.
	/// </summary>
	public class PrinterClass
	{
		//clone of Datagrid
		//private Grid PrintGrid;
		protected List<Grid> PrintGrid;
		
		//printdocument for initial printer settings
		protected PrintDocument PrintDoc;

		//defines whether the grid is ordered right to left
		private bool bRightToLeft;
		
		//Current Top
		private float CurrentY = 0;

		//Current Left
		private float CurrentX = 0;

		//CurrentRow to print
		private int CurrentRow = 0;

		//Page Counter
		public int PageCounter=0;

		protected int GridIndex = 0;

		/// <summary>
		/// Constructor Class
		/// </summary>
		/// <param name="pdocument"></param>
		/// <param name="dgrid"></param>
		public PrinterClass(PrintDocument pdocument, DataGridView dgrid)
		{
			//PrintGrid = new Grid(dgrid);
			PrintGrid = new List<Grid>();
			PrintGrid.Add(new Grid(dgrid));
			PrintDoc = pdocument;

			//The grid columns are right to left
			bRightToLeft = dgrid.RightToLeft == RightToLeft.Yes;

			//init CurrentX and CurrentY
			CurrentY = pdocument.DefaultPageSettings.Margins.Top;
			CurrentX = pdocument.DefaultPageSettings.Margins.Left;


		}

		/// <summary>
		/// Constructor Class.
		/// Prints each grid in the list on a different page
		/// </summary>
		/// <param name="pdocument"></param>
		/// <param name="dgrid"></param>
		public PrinterClass(PrintDocument pdocument, List<DataGridView> dgridlist)
		{
			PrintGrid = new List<Grid>();
			foreach (DataGridView dgrid in dgridlist)
			{
				dgrid[0, 1].Style.Alignment = DataGridViewContentAlignment.MiddleLeft;
				//PrintGrid = new Grid(dgrid);
				PrintGrid.Add(new Grid(dgrid));

				//The grid columns are right to left
				bRightToLeft = dgrid.RightToLeft == RightToLeft.Yes;
			}
			PrintDoc = pdocument;

			//init CurrentX and CurrentY
			CurrentY = pdocument.DefaultPageSettings.Margins.Top;
			CurrentX = pdocument.DefaultPageSettings.Margins.Left;
		}

		public virtual bool Print(Graphics g, ref float currentX, ref float currentY)
		{
			//use predefined area
			CurrentX = currentX;
			CurrentY = currentY;

			PrintHeaders(g);
			bool Morepages = PrintDataGrid(g);

			currentY = CurrentY;
			currentX = CurrentX;

			return Morepages;
		}

		public virtual bool Print(Graphics g)
		{
            if (PrintGrid.Count <= GridIndex)
                GridIndex = 0;
                //return false;

			CurrentX = PrintDoc.DefaultPageSettings.Margins.Left;
			CurrentY = PrintDoc.DefaultPageSettings.Margins.Top;
			PrintHeaders(g);
			return PrintDataGrid(g);
		}

		/// <summary>
		/// Print the Grid Headers
		/// </summary>
		/// <param name="g"></param>
		protected virtual void PrintHeaders(Graphics g)
		{
			StringFormat sf = new StringFormat();

			//if we want to print the grid right to left
			if (bRightToLeft)
			{
				CurrentX = PrintDoc.DefaultPageSettings.PaperSize.Width - PrintDoc.DefaultPageSettings.Margins.Right;
				sf.FormatFlags = StringFormatFlags.DirectionRightToLeft;
			}
			else
			{
				CurrentX = PrintDoc.DefaultPageSettings.Margins.Left;
			}

			//for (int i=0;i<PrintGrid[GridIndex].Columns;i++)
			for (int i = 0; i < PrintGrid[GridIndex].Columns; i++)
			{
				switch (((Header)PrintGrid[GridIndex].Headers.GetValue(i)).Alignment)
				{
					case DataGridViewContentAlignment.BottomCenter:
						sf.Alignment = StringAlignment.Center;
						sf.LineAlignment = StringAlignment.Far;
						break;
					case DataGridViewContentAlignment.MiddleCenter:
						sf.Alignment = StringAlignment.Center;
						sf.LineAlignment = StringAlignment.Center;
						break;
					case DataGridViewContentAlignment.TopCenter:
						sf.Alignment = StringAlignment.Center;
						sf.LineAlignment = StringAlignment.Near;
						break;
					case DataGridViewContentAlignment.BottomLeft:
						sf.Alignment = StringAlignment.Near;
						sf.LineAlignment = StringAlignment.Far;
						break;
					case DataGridViewContentAlignment.MiddleLeft:
						sf.Alignment = StringAlignment.Near;
						sf.LineAlignment = StringAlignment.Center;
						break;
					case DataGridViewContentAlignment.TopLeft:
						sf.Alignment = StringAlignment.Near;
						sf.LineAlignment = StringAlignment.Near;
						break;
					case DataGridViewContentAlignment.BottomRight:
						sf.Alignment = StringAlignment.Far;
						sf.LineAlignment = StringAlignment.Far;
						break;
					case DataGridViewContentAlignment.MiddleRight:
						sf.Alignment = StringAlignment.Far;
						sf.LineAlignment = StringAlignment.Center;
						break;
					case DataGridViewContentAlignment.TopRight:
						sf.Alignment = StringAlignment.Far;
						sf.LineAlignment = StringAlignment.Near;
						break;
					default:
						sf.Alignment = StringAlignment.Near;
						sf.LineAlignment = StringAlignment.Near;
						break;
				}

				//advance X according to order
				if (bRightToLeft)
				{

					//draw the cell bounds (lines) and back color
					g.FillRectangle(new SolidBrush(PrintGrid[GridIndex].HeaderBackColor), CurrentX - PrintGrid[GridIndex].Headers[i].Width, CurrentY, PrintGrid[GridIndex].Headers[i].Width, PrintGrid[GridIndex].Headers[i].Height);
					g.DrawRectangle(new Pen(PrintGrid[GridIndex].LineColor), CurrentX - PrintGrid[GridIndex].Headers[i].Width, CurrentY, PrintGrid[GridIndex].Headers[i].Width, PrintGrid[GridIndex].Headers[i].Height);

					//draw the cell text
					g.DrawString(PrintGrid[GridIndex].Headers[i].Text, PrintGrid[GridIndex].Headers[i].Font, new SolidBrush(PrintGrid[GridIndex].HeaderForeColor), new RectangleF(CurrentX - PrintGrid[GridIndex].Headers[i].Width, CurrentY, PrintGrid[GridIndex].Headers[i].Width, PrintGrid[GridIndex].Headers[i].Height), sf);

					//next cell
					CurrentX -= PrintGrid[GridIndex].Headers[i].Width;

				}
				else
				{

					//draw the cell bounds (lines) and back color
					g.FillRectangle(new SolidBrush(PrintGrid[GridIndex].HeaderBackColor), CurrentX, CurrentY, PrintGrid[GridIndex].Headers[i].Width, PrintGrid[GridIndex].Headers[i].Height);
					g.DrawRectangle(new Pen(PrintGrid[GridIndex].LineColor), CurrentX, CurrentY, PrintGrid[GridIndex].Headers[i].Width, PrintGrid[GridIndex].Headers[i].Height);

					//draw the cell text
					g.DrawString(PrintGrid[GridIndex].Headers[i].Text, PrintGrid[GridIndex].Headers[i].Font, new SolidBrush(PrintGrid[GridIndex].HeaderForeColor), new RectangleF(CurrentX, CurrentY, PrintGrid[GridIndex].Headers[i].Width, PrintGrid[GridIndex].Headers[i].Height), sf);

					//next cell
					CurrentX += PrintGrid[GridIndex].Headers[i].Width;
				}


			}

			//reset to beginning
			if (bRightToLeft)
			{
				//right align
				CurrentX = PrintDoc.DefaultPageSettings.PaperSize.Width - PrintDoc.DefaultPageSettings.Margins.Right;
			}
			else
			{
				//left align
				CurrentX = PrintDoc.DefaultPageSettings.Margins.Left;
			}

			//advance to next row
			CurrentY = CurrentY + ((Header)(PrintGrid[GridIndex].Headers.GetValue(0))).Height;
		}

		protected virtual bool PrintDataGrid(Graphics g)
		{	
			StringFormat sf = new StringFormat();
			PageCounter++;
			
			//if we want to print the grid right to left
			if (bRightToLeft)
			{
				CurrentX = PrintDoc.DefaultPageSettings.PaperSize.Width - PrintDoc.DefaultPageSettings.Margins.Right;
				sf.FormatFlags = StringFormatFlags.DirectionRightToLeft;
			}
			else
			{
				CurrentX = PrintDoc.DefaultPageSettings.Margins.Left;
			}

            //for (int i=CurrentRow;i<=PrintGrid[GridIndex].Rows;i++)
            for (int i = CurrentRow; i < PrintGrid[GridIndex].Rows; i++)
			{
				for (int j=0;j<PrintGrid[GridIndex].Columns;j++)
				{
					switch (PrintGrid[GridIndex][i, j].Alignment)
					{
						case DataGridViewContentAlignment.BottomCenter:
							sf.Alignment = StringAlignment.Center;
							sf.LineAlignment = StringAlignment.Far;
							break;
						case DataGridViewContentAlignment.MiddleCenter:
							sf.Alignment = StringAlignment.Center;
							sf.LineAlignment = StringAlignment.Center;
							break;
						case DataGridViewContentAlignment.TopCenter:
							sf.Alignment = StringAlignment.Center;
							sf.LineAlignment = StringAlignment.Near;
							break;
						case DataGridViewContentAlignment.BottomLeft:
							sf.Alignment = StringAlignment.Near;
							sf.LineAlignment = StringAlignment.Far;
							break;
						case DataGridViewContentAlignment.MiddleLeft:
							sf.Alignment = StringAlignment.Near;
							sf.LineAlignment = StringAlignment.Center;
							break;
						case DataGridViewContentAlignment.TopLeft:
							sf.Alignment = StringAlignment.Near;
							sf.LineAlignment = StringAlignment.Near;
							break;
						case DataGridViewContentAlignment.BottomRight:
							sf.Alignment = StringAlignment.Far;
							sf.LineAlignment = StringAlignment.Far;
							break;
						case DataGridViewContentAlignment.MiddleRight:
							sf.Alignment = StringAlignment.Far;
							sf.LineAlignment = StringAlignment.Center;
							break;
						case DataGridViewContentAlignment.TopRight:
							sf.Alignment = StringAlignment.Far;
							sf.LineAlignment = StringAlignment.Near;
							break;
						default:
							sf.Alignment = StringAlignment.Near;
							sf.LineAlignment = StringAlignment.Near;
							break;
					}
					
					//advance X according to order
					if (bRightToLeft)
					{
						
						//draw the cell bounds (lines) and back color
						g.FillRectangle(new SolidBrush(PrintGrid[GridIndex].BackColor), CurrentX - PrintGrid[GridIndex][i, j].Width, CurrentY, PrintGrid[GridIndex][i, j].Width, PrintGrid[GridIndex][i, j].Height);
						g.DrawRectangle(new Pen(PrintGrid[GridIndex].LineColor), CurrentX - PrintGrid[GridIndex][i, j].Width, CurrentY, PrintGrid[GridIndex][i, j].Width, PrintGrid[GridIndex][i, j].Height);
						
						//draw the cell text
						g.DrawString(PrintGrid[GridIndex][i, j].Text, PrintGrid[GridIndex][i, j].Font, new SolidBrush(PrintGrid[GridIndex].ForeColor), new RectangleF(CurrentX - PrintGrid[GridIndex][i, j].Width, CurrentY, PrintGrid[GridIndex][i, j].Width, PrintGrid[GridIndex][i, j].Height), sf);

						//next cell
						CurrentX -= PrintGrid[GridIndex][i, j].Width;
					
					}
					else
					{
						//draw the cell bounds (lines) and back color
						g.FillRectangle(new SolidBrush(PrintGrid[GridIndex][i, j].BackColor/*.BackColor*/), CurrentX, CurrentY, PrintGrid[GridIndex][i, j].Width, PrintGrid[GridIndex][i, j].Height);//13, 40);//
						g.DrawRectangle(new Pen(PrintGrid[GridIndex].LineColor), CurrentX, CurrentY, PrintGrid[GridIndex][i, j].Width, PrintGrid[GridIndex][i, j].Height);//13,40);//
						
						//draw the cell text
						//Draw text by alignment
						g.DrawString(PrintGrid[GridIndex][i, j].Text, PrintGrid[GridIndex][i, j].Font, new SolidBrush(PrintGrid[GridIndex].ForeColor/*[i, j].FontColor*/), new RectangleF(CurrentX, CurrentY, PrintGrid[GridIndex][i, j].Width, PrintGrid[GridIndex][i, j].Height), sf);
							
						//next cell
						CurrentX += PrintGrid[GridIndex][i, j].Width;
					}
					
					
				}

				//reset to beginning
				if (bRightToLeft)
				{
					//right align
					CurrentX = PrintDoc.DefaultPageSettings.PaperSize.Width - PrintDoc.DefaultPageSettings.Margins.Right;
				}
				else
				{
					//left align
					CurrentX = PrintDoc.DefaultPageSettings.Margins.Left;
				}
				
				//advance to next row
				CurrentY = CurrentY + PrintGrid[GridIndex][i, 0].Height;
				CurrentRow++;
				//if we are beyond the page margin (bottom) then we need another page,
				//return true
				//if (CurrentY > PrintDoc.DefaultPageSettings.PaperSize.Height - PrintDoc.DefaultPageSettings.Margins.Bottom)
				if ((CurrentY > PrintDoc.DefaultPageSettings.PaperSize.Width - PrintDoc.DefaultPageSettings.Margins.Bottom)
					&& !(CurrentRow == PrintGrid[GridIndex].Rows))
				{
					return true;
				}
			}

			GridIndex++;
			if (GridIndex < PrintGrid.Count)
			{
				//Draw a new grid
				CurrentRow = 0;
				return true;
			}

			return false;
		}

	}
}
